home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 5
/
The 640 Meg Shareware Studio CD-ROM Volume V (Data Express)(1994).ISO
/
amiga
/
awwari11.lha
/
Awwari
/
Source
/
Awwari.c
next >
Wrap
C/C++ Source or Header
|
1994-05-09
|
21KB
|
719 lines
/*
* Awwari - An Awari game by ! Wizard Works !
* Written by Stefan Zeiger in 1993-1994
* (c) 1993-1994 by Stefan Zeiger
* Freely distributable, All other rights reserved
*
* I am not very proud of this piece of source. I hacked the first
* first version together on one afternoon. Don't blame me if you
* can't make your way through this code jungle ;)
*
* 22.11.1993 0.1 Project started
* 23.11.1993 0.2 Playable; dumb computer
* 27.11.1993 0.3 AwariMove() added, PerformMove() rewritten to use AwariMove()
* 0.4 Simple computer strategy added
* 28.11.1993 0.5 Auto finish added
* 0.6 Recursive computer strategy added
* 12.11.1993 0.7 Updated with new Triton system
* 23.12.1993 1.0 First release, using Triton 0.106
* 20.04.1994 1.1b1 Rewritten for triton.library
* 09.05.1994 1.1 Released Awwari 1.1
*
*/
#define AWWARI_VERSION "1.1"
#define AWWARI_DATE "9.5.94"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////// Include our stuff //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <libraries/triton.h>
#include <proto/intuition.h>
#include <proto/triton.h>
#include <proto/dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////// Windows //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
ProjectDefinition(about_trwintags)
{
BeginRequester("About Awwari...",TRWP_MOUSEPOINTER),
VertGroupA, Space, CenteredText3("Awwari " AWWARI_VERSION),
Space, CenteredText_BS("An Awari game by ! Wizard Works !"),
Space, CenteredText("⌐ 1993-1994 by Stefan Zeiger"),
Space, HorizSeparator,
Space, CenteredText("This program is using the"),
SpaceS, CenteredText("Triton GUI creation system"),
SpaceS, CenteredText("which is ⌐ by Stefan Zeiger"),
Space, EndGroup,
BeginRequesterGads,
CenteredButtonRE("_OK",1),
EndRequester
};
STRPTR cycle_entries_player[]=
{
"Human",
"Computer",
NULL
};
STRPTR cycle_entries_first[]=
{
"Player 1",
"Player 2",
"Random",
NULL
};
STRPTR cycle_entries_level[]=
{
"1",
"2",
"3",
"4",
"5",
NULL
};
ProjectDefinition(main_trwintags)
{
WindowTitle("Awwari " AWWARI_VERSION " - ⌐ 1993-1994 by Stefan Zeiger"),
WindowPosition(TRWP_CENTERDISPLAY), WindowID(1),
BeginMenu("Project"),
MenuItem("?_About...",1001),
ItemBarlabel,
MenuItem("Q_Quit",1002),
VertGroupA,
Space, NamedSeparator("Options"),
Space, HorizGroupEAC,
HorizGroupS, Space, TextN("Pl_ayer 1"), TRAT_ID, 102, EndGroup,
SpaceB,
TROB_Cycle, (ULONG) cycle_entries_player,
TRAT_ID, (ULONG) 102,
TRAT_Value, (ULONG) 0,
Space,
HorizGroupS, Space, TextN("_First move"), TRAT_ID, 104, EndGroup,
SpaceB,
TROB_Cycle, (ULONG) cycle_entries_first,
TRAT_ID, (ULONG) 104,
TRAT_Value, (ULONG) 2,
Space,
EndGroup,
Space, HorizGroupEAC,
HorizGroupS, Space, TextN("Pla_yer 2"), TRAT_ID, 103, EndGroup,
SpaceB,
TROB_Cycle, (ULONG) cycle_entries_player,
TRAT_ID, (ULONG) 103,
TRAT_Value, (ULONG) 1,
Space,
HorizGroupS, Space, TextN("_Level"), TRAT_ID, 105, EndGroup,
SpaceB,
TROB_Cycle, (ULONG) cycle_entries_level,
TRAT_ID, (ULONG) 105,
TRAT_Value, (ULONG) 0,
Space,
EndGroup,
Space, HorizGroupE, Space, ButtonR("_Start game",110), Space, Button("_Quit game",112), Disabled, Space, Button("A_uto finish",111), Disabled, Space, EndGroup,
Space, NamedSeparator("Status"),
Space, HorizGroup, Space, FrameBox, ObjectBackfillB, VertGroup|TRGR_FIXVERT, SpaceS, HorizGroupSC, Space, TextN("Ready."),ID(101), TRAT_MinWidth, 40, Space, EndGroup, SpaceS, EndGroup, Space, EndGroup,
Space, NamedSeparator("Playfield"),
Space, HorizGroupEA,
Space, VertGroupA, SpaceS, CenteredText3("1"), SpaceS, EndGroup,
Space, IntegerBox(3,6,3),
Space, IntegerBox(3,5,3),
Space, IntegerBox(3,4,3),
Space, IntegerBox(3,3,3),
Space, IntegerBox(3,2,3),
Space, IntegerBox(3,1,3),
Space, HorizGroupS, Space, EndGroup,
Space, EndGroup,
Space, HorizGroupEAC,
Space, IntegerBox(0,7,3),
Space, Button("_1",201), Disabled,
Space, Button("_2",202), Disabled,
Space, Button("_3",203), Disabled,
Space, Button("_4",204), Disabled,
Space, Button("_5",205), Disabled,
Space, Button("_6",206), Disabled,
Space, IntegerBox(0,17,3),
Space, EndGroup,
Space, HorizGroupEA,
Space, HorizGroupS, Space, EndGroup,
Space, IntegerBox(3,11,3),
Space, IntegerBox(3,12,3),
Space, IntegerBox(3,13,3),
Space, IntegerBox(3,14,3),
Space, IntegerBox(3,15,3),
Space, IntegerBox(3,16,3),
Space, VertGroupA, SpaceS, CenteredText3("2"), SpaceS, EndGroup,
Space, EndGroup,
Space, EndGroup, EndProject
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////// Our own names //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID SetInfoString (STRPTR);
VOID StartGame (VOID);
VOID QuitGame (VOID);
VOID Winner (UWORD);
VOID MakeTurn (UWORD player, BOOL setsecondturn);
VOID SetPositionGadgets (UWORD);
VOID DisablePositionGadgets (VOID);
VOID ActualizeDisplay (VOID);
VOID PerformMove (UWORD,UWORD);
VOID ComputeMove (UWORD);
UWORD BestMove (UBYTE awarifield[7][2], UWORD aplayer, UWORD *bestval);
UWORD BestMoveNR (UBYTE awarifield[7][2], UWORD aplayer);
UWORD AwariMove (UBYTE awarifield[7][2], UWORD player, UWORD field);
struct TR_Project * main_project;
UWORD player1,
player2,
first,
level,
currentplayer,
currentdepth;
BOOL gamerunning;
UBYTE playfield [7][2];
UBYTE display [7][2];
UWORD i,
j;
BOOL posgaddisabled [6];
BOOL secondturn;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////// Main function //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID do_main(VOID)
{
BOOL close_me=FALSE;
struct TR_Message *trmsg;
for(i=0;i<=1;i++)
{
for(j=0;j<=5;j++) display[j][i]=3;
display[6][i]=0;
}
for(j=0;j<=5;j++) posgaddisabled[j]=TRUE;
if(main_project=TR_OpenProject(Application,main_trwintags))
{
while(!close_me)
{
TR_Wait(Application,NULL);
while(trmsg=TR_GetMsg(Application))
{
switch(trmsg->trm_Class)
{
case TRMS_CLOSEWINDOW:
close_me=TRUE;
break;
case TRMS_ERROR:
DisplayBeep(NULL);
break;
case TRMS_NEWVALUE:
break;
case TRMS_ACTION:
switch(trmsg->trm_ID)
{
case 110:
StartGame();
break;
case 111:
player1=1;
player2=1;
TR_SetAttribute(main_project,112,TRAT_Disabled,1L);
TR_SetAttribute(main_project,111,TRAT_Disabled,1L);
MakeTurn(currentplayer,FALSE);
break;
case 112:
QuitGame();
SetInfoString("Ready.");
break;
case 201:
PerformMove(currentplayer,currentplayer?0:5);
break;
case 202:
PerformMove(currentplayer,currentplayer?1:4);
break;
case 203:
PerformMove(currentplayer,currentplayer?2:3);
break;
case 204:
PerformMove(currentplayer,currentplayer?3:2);
break;
case 205:
PerformMove(currentplayer,currentplayer?4:1);
break;
case 206:
PerformMove(currentplayer,currentplayer?5:0);
break;
case 1001:
TR_AutoRequest(Application,main_project,about_trwintags);
break;
case 1002:
close_me=TRUE;
}
break;
}
TR_ReplyMsg(trmsg);
}
}
TR_CloseProject(main_project);
}
else DisplayBeep(NULL);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////// Entry function //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main(void)
{
if(TR_OpenTriton(TRITON10VERSION,
TRCA_Name, "Awwari",
TRCA_LongName,"Awwari",
TRCA_Info, "An Awari game for the Workbench\nWritten and ⌐ 1993-1994 by Stefan Zeiger",
TRCA_Release, "1.1",
TRCA_Date, AWWARI_DATE,
TAG_END))
{
do_main();
TR_CloseTriton();
return 0;
}
puts("Can't open triton.library.");
return 20;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////// Evaluate a move //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
UWORD MyRand(VOID)
{
unsigned int clock[2];
WORD seed[3];
(VOID)timer(clock);
seed[0]=(WORD)clock[0];
seed[1]=(WORD)clock[1]>>16;
seed[2]=(WORD)clock[1];
return (UWORD)(jrand48((UWORD *)seed));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////// Evaluate a move //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define AM_OK 0L
#define AM_EMPTYFIELD 1L
#define AM_EXTRATURN 2L
#define AM_1WINS 3L
#define AM_2WINS 4L
#define AM_TIE 5L
UWORD AwariMove(UBYTE awarifield[7][2], UWORD aplayer, UWORD afield)
{
UBYTE stonesleft=awarifield[afield][aplayer];
UBYTE cfield=afield;
UBYTE cplayer=aplayer;
UBYTE nextplayer;
if(stonesleft==0) return AM_EMPTYFIELD;
awarifield[afield][aplayer]=0;
while(stonesleft>0)
{
cfield++;
if(cfield==7) { cfield=0; cplayer++; cplayer%=2; }
awarifield[cfield][cplayer]++;
stonesleft--;
}
if(cfield!=6)
{
if((awarifield[cfield][cplayer]==1)&&(awarifield[5-cfield][(cplayer+1)%2]!=0))
{
awarifield[6][aplayer]+=(awarifield[cfield][cplayer]+awarifield[5-cfield][(cplayer+1)%2]);
awarifield[cfield][cplayer]=0;
awarifield[5-cfield][(cplayer+1)%2]=0;
}
}
if((cplayer==aplayer)&&(cfield==6)) nextplayer=aplayer; else nextplayer=(aplayer+1)%2;
if(awarifield[6][0]>18) return AM_1WINS;
if(awarifield[6][1]>18) return AM_2WINS;
if( (awarifield[0][nextplayer]==0) &&
(awarifield[1][nextplayer]==0) &&
(awarifield[2][nextplayer]==0) &&
(awarifield[3][nextplayer]==0) &&
(awarifield[4][nextplayer]==0) &&
(awarifield[5][nextplayer]==0) )
{
if(awarifield[6][0]==awarifield[6][1]) return AM_TIE;
if(awarifield[6][0]>awarifield[6][1]) return AM_1WINS;
return AM_2WINS;
}
if(nextplayer==aplayer) return AM_EXTRATURN; else return AM_OK;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////// Helping functions //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID SetInfoString(STRPTR istr)
{
TR_SetAttribute(main_project,101,TRAT_Text,(ULONG)istr);
}
VOID StartGame()
{
for(i=0;i<=1;i++)
{
for(j=0;j<=5;j++) playfield[j][i]=3;
playfield[6][i]=0;
}
TR_SetAttribute(main_project,102,TRAT_Disabled,1L);
TR_SetAttribute(main_project,103,TRAT_Disabled,1L);
TR_SetAttribute(main_project,104,TRAT_Disabled,1L);
TR_SetAttribute(main_project,105,TRAT_Disabled,1L);
TR_SetAttribute(main_project,110,TRAT_Disabled,1L);
player1=TR_GetAttribute(main_project,102,TRAT_Value);
player2=TR_GetAttribute(main_project,103,TRAT_Value);
first=TR_GetAttribute(main_project,104,TRAT_Value);
level=TR_GetAttribute(main_project,105,TRAT_Value)+1;
if((player1==0)||(player2==0))
{
TR_SetAttribute(main_project,112,TRAT_Disabled,0L);
TR_SetAttribute(main_project,111,TRAT_Disabled,0L);
}
if(first==2) currentplayer=((MyRand())&(1<<7))>>7; else currentplayer=first;
gamerunning=TRUE;
ActualizeDisplay();
MakeTurn(currentplayer,TRUE);
}
VOID QuitGame()
{
TR_SetAttribute(main_project,102,TRAT_Disabled,0L);
TR_SetAttribute(main_project,103,TRAT_Disabled,0L);
TR_SetAttribute(main_project,104,TRAT_Disabled,0L);
TR_SetAttribute(main_project,105,TRAT_Disabled,0L);
TR_SetAttribute(main_project,112,TRAT_Disabled,1L);
TR_SetAttribute(main_project,111,TRAT_Disabled,1L);
TR_SetAttribute(main_project,110,TRAT_Disabled,0L);
DisablePositionGadgets();
gamerunning=FALSE;
}
VOID Winner(UWORD player)
{
QuitGame();
switch(player)
{
case 0:
SetInfoString("Player 1 wins.");
break;
case 1:
SetInfoString("Player 2 wins.");
break;
default:
SetInfoString("A tie.");
break;
}
}
VOID MakeTurn(UWORD player, BOOL setsecondturn)
{
if(setsecondturn) secondturn=FALSE;
if(player==0)
{
if(player1==0)
{
SetInfoString("Make your turn, player 1.");
SetPositionGadgets(0);
}
else
{
SetInfoString("Player 1 is thinking...");
DisablePositionGadgets();
ComputeMove(0);
}
}
else
{
if(player2==0)
{
SetInfoString("Make your turn, player 2.");
SetPositionGadgets(1);
}
else
{
SetInfoString("Player 2 is thinking...");
DisablePositionGadgets();
ComputeMove(1);
}
}
}
VOID SetPositionGadgets(UWORD player)
{
BOOL newval;
UWORD k;
for(j=0;j<=5;j++)
{
newval=playfield[j][player]?0L:1L;
if(player==0) k=5-j; else k=j;
if(posgaddisabled[k]!=newval?1L:0L)
{
TR_SetAttribute(main_project,201+k,TRAT_Disabled,(UWORD)newval);
posgaddisabled[k]=newval;
}
}
}
VOID DisablePositionGadgets(VOID)
{
for(j=0;j<=5;j++) if(!posgaddisabled[j])
{
TR_SetAttribute(main_project,201+j,TRAT_Disabled,1L);
posgaddisabled[j]=1L;
}
}
VOID ActualizeDisplay()
{
for(i=0;i<=1;i++) for(j=0;j<=6;j++) if(display[j][i]!=playfield[j][i])
{
display[j][i]=playfield[j][i];
TR_SetAttribute(main_project,1+(i*10)+j,TRAT_Value,playfield[j][i]);
}
}
VOID PerformMove(UWORD player, UWORD field)
{
UWORD result;
result=AwariMove(playfield,player,field);
ActualizeDisplay();
switch(result)
{
case AM_1WINS:
case AM_2WINS:
case AM_TIE:
Winner(result-3);
return;
case AM_EXTRATURN:
if(!secondturn)
{
secondturn=TRUE;
SetPositionGadgets(currentplayer);
if(currentplayer==0)
{
if(player1==0) SetInfoString("Extra turn, player 1.");
else
{
SetInfoString("Extra turn. Player 1 is thinking...");
DisablePositionGadgets();
ComputeMove(0);
}
}
else
{
if(player2==0) SetInfoString("Extra turn, player 2.");
else
{
SetInfoString("Extra turn. Player 2 is thinking...");
DisablePositionGadgets();
ComputeMove(1);
}
}
return;
}
case AM_OK:
currentplayer++;
currentplayer%=2;
MakeTurn(currentplayer,TRUE);
return;
case AM_EMPTYFIELD:
DisplayBeep(NULL);
return;
}
}
VOID ComputeMove(UWORD player)
{
UWORD num;
TR_LockProject(main_project);
//Delay(50L);
currentdepth=0;
num=BestMove(playfield,player,NULL);
if(playfield[num][player]) PerformMove(player,num);
else if(playfield[0][player]) PerformMove(player,0);
else if(playfield[1][player]) PerformMove(player,1);
else if(playfield[2][player]) PerformMove(player,2);
else if(playfield[3][player]) PerformMove(player,3);
else if(playfield[4][player]) PerformMove(player,4);
else if(playfield[5][player]) PerformMove(player,5);
else PerformMove(currentplayer,2);
TR_UnlockProject(main_project);
}
UWORD BestMove(UBYTE awarifield[7][2], UWORD aplayer, UWORD *bestval)
{
UBYTE dest[6][7][2];
register UWORD result;
register UWORD i,j,k;
register UBYTE val=0, newval, retval=0;
UWORD recurseval,otherplayer;
currentdepth++;
for(i=0;i<7;i++) for(j=0;j<2;j++) for(k=0;k<6;k++) dest[k][i][j]=awarifield[i][j];
for(k=0;k<6;k++)
{
if(currentdepth>=level)
{
result=AwariMove(dest[k],aplayer,k);
newval=dest[k][6][aplayer];
switch(result)
{
case AM_EXTRATURN:
newval++;
break;
case AM_1WINS:
if(aplayer==0) newval=255; else newval=0;
break;
case AM_2WINS:
if(aplayer==1) newval=255; else newval=0;
break;
case AM_TIE:
if(newval>0) newval--;
break;
case AM_EMPTYFIELD:
newval=0;
break;
}
}
else
{
if((result=AwariMove(dest[k],aplayer,k)==AM_EXTRATURN)&&((secondturn==FALSE)||(currentdepth>1)))
result=AwariMove(dest[k],aplayer,BestMoveNR(dest[k],aplayer));
otherplayer=(aplayer+1)%2;
if(AwariMove(dest[k],otherplayer,BestMoveNR(dest[k],otherplayer))==AM_EXTRATURN)
AwariMove(dest[k],otherplayer,BestMoveNR(dest[k],otherplayer));
BestMove(dest[k],aplayer,&recurseval);
newval=recurseval;
if((result==AM_EXTRATURN)&&((secondturn==FALSE)||(currentdepth>1))) newval++;
}
if( (newval>val) || ((newval==val)&&( ((MyRand())&(1<<7))>>7 == 1)) )
{
val=newval;
retval=k;
}
}
currentdepth--;
if(bestval) *bestval=val;
return retval;
}
UWORD BestMoveNR(UBYTE awarifield[7][2], UWORD aplayer)
{
UBYTE dest[6][7][2];
register UWORD result;
register UWORD i,j,k;
register UBYTE val=0, newval, retval=0;
for(i=0;i<7;i++) for(j=0;j<2;j++) for(k=0;k<6;k++) dest[k][i][j]=awarifield[i][j];
for(k=0;k<6;k++)
{
result=AwariMove(dest[k],aplayer,k);
newval=dest[k][6][aplayer];
switch(result)
{
case AM_EXTRATURN:
newval++;
break;
case AM_1WINS:
if(aplayer==0) newval=255; else newval=0;
break;
case AM_2WINS:
if(aplayer==1) newval=255; else newval=0;
break;
case AM_TIE:
if(newval>0) newval--;
break;
case AM_EMPTYFIELD:
newval=0;
break;
}
if( (newval>val) || ((newval==val)&&( ((MyRand())&(1<<7))>>7 == 1)) )
{
val=newval;
retval=k;
}
}
return retval;
}